/**
 * 
 */
package org.demetra.core;

import java.util.concurrent.ExecutorService;

import com.ericsson.otp.erlang.OtpErlangAtom;
import com.ericsson.otp.erlang.OtpErlangExit;
import com.ericsson.otp.erlang.OtpErlangObject;
import com.ericsson.otp.erlang.OtpErlangPid;
import com.ericsson.otp.erlang.OtpMbox;
import com.ericsson.otp.erlang.OtpNode;

/**
 * @author vvorobyov
 *
 */
public class ServerLoop extends WorkerLoop {

	public static final OtpErlangAtom JETS_OPEN_SESS = new OtpErlangAtom("open");
	public static final OtpErlangAtom OK = new OtpErlangAtom("ok");
	private OtpNode _node;
	private ExecutorService _executor;
	private Server _srv;

	/**
	 * @param mbox
	 */
	public ServerLoop(Server aSrvCallback, OtpNode aNode, ExecutorService aExecutor) {
		super(aNode.createMbox("srv_jets"));
		_node=aNode;
		_executor = aExecutor;
		_srv=aSrvCallback;
	}
	
	@Override
	protected void init() throws Exception {
		super.init();
		_srv.init(_node);
	}

	/* (non-Javadoc)
	 * @see org.demetra.jets.WorkerLoop#close()
	 */
	@Override
	protected void close() throws Exception {
		try{
			_executor.shutdown();
		}
		finally{
			_srv.shutdown();
			super.close();
		}
	}

	/* (non-Javadoc)
	 * @see org.demetra.jets.WorkerLoop#handleRequest(com.ericsson.otp.erlang.OtpErlangAtom, com.ericsson.otp.erlang.OtpErlangObject)
	 */
	@Override
	protected OtpErlangObject handleRequest(OtpErlangAtom opCode,
			OtpErlangObject requestData) {
		if(opCode.equals(JETS_OPEN_SESS)){
			try {
				OtpErlangPid pidSessLinkTo = ((OtpErlangPid)requestData);
				OtpMbox sessMbox = _node.createMbox();
				sessMbox.link(pidSessLinkTo);
				_executor.execute(_srv.createSession(sessMbox));
				return tuple(OK,sessMbox.self());//{ok,SessPid}
			} catch (ClassCastException e) {
				throw new JetsException(e,tuple(atom("not_a_pid"),requestData));
			} catch (OtpErlangExit e) {
				throw new JetsException(e,tuple(atom("open_err"),e.reason()));
			}
		}
		throw new JetsException(tuple(atom("bad_opcode"),opCode));
	}
}
